"""
this class computes the monoid for an automaton and contains the principal data
"""
from automatadefs import fsa
class monoid:


    def __init__(self,automaton,name='untitled',type='plant'):
        relation,represent,rightCayleyAut,leftCayleyAut,idempotents,zero = aut2monoid(automaton)
        rightCayleyAut.name, leftCayleyAut.name = name, name   
        rightCayleyAut.type, leftCayleyAut.type = type, type       
        self.relation = relation
        self.represent = represent
        self.rcayley = rightCayleyAut
        self.lcayley = leftCayleyAut
        self.idem = idempotents
        self.zero = zero
        self.name= name
        return
    
    def greenrelations(self):
        
        right, left= self.rcayley.nxGraph, self.lcayley.nxGraph
        Rclass=nx.algorithms.components.strongly_connected.strongly_connected_components(right)
        Lclass=nx.algorithms.components.strongly_connected.strongly_connected_components(left)
        unionLR=nx.algorithms.operators.compose(left,right)
        Jclass=nx.algorithms.components.strongly_connected.strongly_connected_components(unionLR)
        
        return Lclass, Rclass, Jclass
    
def aut2monoid(auto):    
    delta = auto.delta    
    def compute_new_transition(transition,event):        
        nextTransition = []
        nextTranString =''
        for state in transition:
            if state <> '-':
                nextState = delta(state,event)
                if nextState == None :
                    nextState = '-'
            else:
                nextState = '-'
                                                       
            nextTransition.append(nextState)
            nextTranString = nextTranString+','+str(nextState)
            nextTranString = nextTranString.lstrip(',')
        return nextTransition, nextTranString
    
           
    
    Xord = list(auto.X)
    Xord.sort()
    Eord = list(auto.E)
    Eord.sort()
    
    sizeofMonoid=len(Xord)        
    transMonoid=[]
    representative=[epsilon]+Eord
    #symRepres=[Symbol(rep) for rep in representative]
    transMonoid.append(Xord)
    relations={}
    #symRelations=[]
    dictRepres={}
    newTransition,strnewTransition = compute_new_transition(Xord,epsilon)        

    invdictMonoid={strnewTransition:epsilon}
    index=1
    rightCayleyTrans=[]
    leftCayleyTrans=[]
    
        
    for event in Eord:
        dictRepres[event]=index
        transition = transMonoid[0]  
        newTransition,strnewTransition=compute_new_transition(transition,event)
        invdictMonoid[strnewTransition]=event
        transMonoid.append(newTransition)  
        rightCayleyTrans.append([epsilon,event,event])  
        leftCayleyTrans.append([epsilon,event,event])   
        index+=1
    
    
    actRepresList = Eord     
    lenghtLastRepres=1
    leftCayleyTrans
    nullTransition=['-' for state in Xord]
    zero=['nz']
    
    while (lenghtLastRepres <= sizeofMonoid) & (actRepresList <> [])  :        
        newCandList=[]             

        for actRepres in actRepresList:                                    
            for event in Eord:                
                transition = transMonoid[dictRepres[actRepres]]           
                newTransition,strnewTransition=compute_new_transition(transition,event)
                newRepres=actRepres+'*'+event 
                newLeftRepres=event+'*'+actRepres

                if not invdictMonoid.has_key(strnewTransition) :                  
                    transMonoid.append(newTransition)
                    
                    if newTransition == nullTransition:
                        zero=newRepres                                    
                                                                                
                    representative.append(newRepres)                           
                    dictRepres[newRepres]=index 
                    invdictMonoid[strnewTransition] = newRepres    
                    newCandList.append(newRepres)
                    rightCayleyTrans.append([actRepres,event,newRepres])                          
                    index+=1
                else:
                    equivalent = invdictMonoid[strnewTransition]
                    rightCayleyTrans.append([actRepres,event,equivalent])                   
                    relations.update({newRepres:equivalent})
                    dictRepres[newRepres]=dictRepres[actRepres]                    
              
        actRepresList = newCandList              
        lastRepres = newRepres.replace('*','')
        lenghtLastRepres =len(lastRepres)
        
    
    Xc=representative
    X0c=[epsilon]
    Xmc=[]    
    rightCayleyAut =fsa(Xc,Eord,rightCayleyTrans,X0c,
                        Xmc,Eobs=auto.Eobs,Econ=auto.Econ,type='result')
 
     # calculating idempotents
    
    idempotents=[]
    for state in representative[1:]:
        sequence=state.split('*')
        result = rightCayleyAut.delta(state,sequence)
        if state == result:
            idempotents.append(state)

  #  calculating transitions for leftCayleyGraph
    
    for actRepres in representative[1:]:
        for event in Eord:
            leftResult= [event]+actRepres.split('*')
            nextRepres=rightCayleyAut.delta(epsilon,leftResult)
            leftCayleyTrans.append([actRepres,event,nextRepres])
    
    leftCayleyAut =fsa(Xc,Eord,leftCayleyTrans,X0c,Xmc,
                       Eobs=auto.Eobs,Econ=auto.Econ,type='plant')    
               
    return relations,representative,rightCayleyAut,leftCayleyAut,idempotents,zero
